﻿using Mysoft.Map.Extensions.DAL;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Mysoft.QuickCode.Common
{
    /// <summary>
    /// 对象转换类
    /// </summary>
    public static class ObjectConvert
    {
        #region 对象属性复制
        /// <summary>
        /// 属性是否相等
        /// </summary>
        class PropertyInfoComparer : IEqualityComparer<PropertyInfo>
        {
            /// <summary>
            /// 比较对象的两个属性是否一致
            /// </summary>
            /// <param name="x"></param>
            /// <param name="y"></param>
            /// <returns></returns>
            public bool Equals(PropertyInfo x, PropertyInfo y)
            {
                //比较属性类型和属性名称是否一样
                return x.PropertyType == y.PropertyType
                    && x.Name == y.Name;
            }

            public int GetHashCode(PropertyInfo obj)
            {
                return obj.PropertyType.GetHashCode() ^ obj.Name.GetHashCode();
            }
        }
        /// <summary>
        /// 对象转换为新的实体对象，只有公开的实例属性才会被转换为目标对象的属性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="srcObj"></param>
        /// <returns></returns>
        public static T ToEntity<T>(object srcObj)
            where T : class, new()
        {
            if (srcObj == null)
            {
                return null;
            }

            PropertyInfo[] tProperties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            PropertyInfo[] srcProperties = srcObj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
            PropertyInfo[] mixedProperties = tProperties
                .Intersect<PropertyInfo>(srcProperties, new PropertyInfoComparer())
                .ToArray();
            T t = new T();
            foreach (PropertyInfo item in mixedProperties)
            {
                item.SetValue(t, item.GetValue(srcObj, null), null);
            }
            return t;
        }

        #endregion

        #region 实体保存设置默认值（基于小平台的实体实现）

        /// <summary>
        /// 小平台实体在设置属性的时候，在字段默认值=构造函数初始化后的实例默认值的时候，默认为字段不生成sql更新语句
        /// 因此扩展此方法，将相关的字段设置默认值，让字段生成保存语句
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj">要设置默认值的对象</param>
        /// <param name="propertyNames">属性名称集合</param>
        public static void SetPropertyDefaultValue<T>(this T obj, List<string> propertyNames)
            where T : BaseEntity
        {
            if (propertyNames == null)
            {
                return;
            }
            Type type = typeof(T);
            foreach (string item in propertyNames)
            {
                PropertyInfo p = type.GetProperty(item);
                //值类型，且值为对应数据类型的初始值的情况下，设置默认值
                if (p != null
                    && p.PropertyType.IsValueType)
                {
                    //Nullable<>默认值判断
                    object typeDefaultValue = (p.PropertyType.IsGenericType 
                        && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) ? null : (object)0;
                    if (p.GetValue(obj, null) == typeDefaultValue)
                    {
                        obj.SetPropertyDefaultValue(item);
                    }
                }
            }
        }

        #endregion
    }
}
